use std::{any::{TypeId, Any}, sync::RwLock};
use crate::*;
use crate::{world::World, entity::{self, Entity, EntityMigrator}, MangoEcsError, archetype::{ArchetypeChannel, Archetype}};

#[derive(Debug,PartialEq, PartialOrd,Eq, Ord,Hash,Clone, Copy)]
pub struct ComponentId(TypeId);

pub(crate) fn get_component_id<T:'static + ComponentTrait>() -> ComponentId {
    ComponentId(TypeId::of::<T>())
}

pub trait ComponentTrait:'static + Send + Sync +Sized {
    fn get_component_id(&self) -> ComponentId {
        ComponentId(TypeId::of::<Self>())
    }

    fn clone_component(_entity_migrator:&mut EntityMigrator,_items:&[Self]) -> Option<Vec<Self>> { None }
}

// pub(crate) fn get_component_id(&self)

pub(crate) trait ComponentChannelVecTrait:Send + Sync {
    fn as_any(&self) -> &dyn Any;
    fn as_any_mut(&mut self) -> &mut dyn Any;
    ///新建同类型 channel
    fn new_same_type(&self) -> Box<dyn ComponentChannelVecTrait>;
    /// 迁移组件
    fn migrate_component(&mut self, index: usize, other: &mut dyn ComponentChannelVecTrait);
    ///交换删除
    fn swap_remove(&mut self, index: usize);

    fn assign(&mut self, index: usize, component: &mut dyn AnyComponentTrait);
    fn push(&mut self, component: &mut dyn AnyComponentTrait);
    fn append_channel(&mut self, other: &mut dyn ComponentChannelVecTrait);
    fn clone_channel(
        &mut self,
        entity_migrator: &mut EntityMigrator,
    ) -> Option<Box<dyn ComponentChannelVecTrait>>;
    fn len(&mut self) -> usize;
    
}


impl <T:ComponentTrait> ComponentChannelVecTrait for RwLock<Vec<T>> {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }

    fn new_same_type(&self) -> Box<dyn ComponentChannelVecTrait> {
        Box::new(RwLock::new(Vec::<T>::new()))
    }

    fn migrate_component(&mut self, index: usize, other: &mut dyn ComponentChannelVecTrait) {
        let data:T = self.get_mut().unwrap().swap_remove(index);
        other.as_any_mut()
            .downcast_mut::<RwLock<Vec<T>>>()
            .unwrap()
            .get_mut()
            .unwrap()
            .push(data)
    }

    fn swap_remove(&mut self, index: usize) {
        self.get_mut().unwrap().swap_remove(index);
    }

    fn assign(&mut self, index: usize, component: &mut dyn AnyComponentTrait) {
        self.get_mut().unwrap()[index] = component.as_any_mut()
            .downcast_mut::<Option<T>>()
            .unwrap()
            .take()
            .unwrap();
    }

    fn push(&mut self, component: &mut dyn AnyComponentTrait) {
        self.get_mut().unwrap().push(component.as_any_mut()
        .downcast_mut::<Option<T>>()
        .unwrap()
        .take()
        .unwrap())
    }

    fn append_channel(&mut self, other: &mut dyn ComponentChannelVecTrait) {
        let other = other.as_any_mut()
            .downcast_mut::<RwLock<Vec<T>>>()
            .unwrap().get_mut().unwrap();

        self.get_mut().unwrap().append(other);
    }

    fn clone_channel(
        &mut self,
        entity_migrator: &mut EntityMigrator,
    ) -> Option<Box<dyn ComponentChannelVecTrait>> {
        Some(Box::new(RwLock::new(T::clone_component(entity_migrator, self.get_mut().unwrap())?)))
    }

    fn len(&mut self) -> usize {
        self.get_mut().unwrap().len()
    }
}


pub trait ComponentBundleTrait:'static + Send + Sync {
    fn add_to_entity(self,world:&mut World,entity:Entity) -> Result<(),MangoEcsError>;
}

impl<C:ComponentTrait> ComponentBundleTrait for C {
    fn add_to_entity(self,world:&mut World,entity:Entity) -> Result<(),MangoEcsError> {
        (self,).add_to_entity(world,entity)
        // todo!()
        // (self,)
    }
}


pub(crate) trait AnyComponentTrait :Any {
    fn new_archetype_channel(&self) -> ArchetypeChannel;
    fn as_any_mut(&mut self) -> &mut dyn Any;
    
}


impl<C:ComponentTrait> AnyComponentTrait for Option<C> {
    fn new_archetype_channel(&self) -> ArchetypeChannel {
        ArchetypeChannel::new::<C>()
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}

pub(crate) fn merge_sorted_iter<T:Ord>(
    capacity:usize,
    mut iter0: impl Iterator<Item = T>,
    mut iter1: impl Iterator<Item = T>,
) -> Vec<T> {
    use std::cmp::Ordering;
    let mut output = Vec::with_capacity(capacity);
    let mut item0 = iter0.next();
    let mut item1 = iter1.next();

    loop {
        output.push(match (item0.is_some(),item1.is_some()) {
            (true, true) => match item0.cmp(&item1) {
                Ordering::Less => {
                    let item = item0.take().unwrap();
                    item0 = iter0.next();
                    item

                },
                Ordering::Equal => {
                    let item = item0.take().unwrap();
                    item0 = iter0.next();
                    item1 = iter1.next();
                    item
                },
                Ordering::Greater => {
                    let item = item1.take().unwrap();
                    item1 = iter1.next();
                    item
                },
            },
            (true, false) => {
                let item = item0.take().unwrap();
                    item0 = iter0.next();
                    item
            },
            (false, true) => {
                let item = item1.take().unwrap();
                    item1 = iter1.next();
                    item
            },
            (false, false) => break,
        })
    }

    output
}

pub(crate) fn add_components_to_entity_inner(world:&mut World,
entity:Entity,
components_and_component_ids:&mut [(&mut dyn AnyComponentTrait,ComponentId)]
) -> Result<(),MangoEcsError> {
    let entity_location = world
        .entities
        .get_entity_location(entity)
        .ok_or(MangoEcsError::EntityMissing)?;

    components_and_component_ids.sort_unstable_by_key(|(_,cmp_id)|*cmp_id);

    // 获取entity 之前的 archetype ,
    let old_archetype = &world.archetypes[entity_location.archetype_index];
    // 获取entity 添加组件之后的所有组件
    let new_components_ids = merge_sorted_iter(old_archetype.channels.len() + components_and_component_ids.len(), old_archetype.channels.iter().map(|c|c.component_id), components_and_component_ids.iter().map(|c|c.1));

    let World {
        archetypes,
        components_ids_to_archetype_index,
        storage_lookup,
        entities,
        ..
    } = world;


    // 通过最新的 component ids 查找或生成新的 Archetype
    let new_archetype_index = {
        let components_and_component_ids = &components_and_component_ids;
        components_ids_to_archetype_index.entry(new_components_ids)
        .or_insert_with_key(|key|{
            // 创建新的 Archetype
            let new_archetype_index = archetypes.len();
            let  mut new_archetype = Archetype::new(new_archetype_index);

            let old_archetype = &mut archetypes[entity_location.archetype_index];

            new_archetype.channels.reserve(key.len());

            for channel in &mut old_archetype.channels {
                let new_channel = channel.new_same_type();
                new_archetype.channels.push(new_channel);
            }

            // 新增增量组件到新的 Archetype
            // 因为新增的组件是不能重复的,所有无需去重
            for component in components_and_component_ids.iter() {
                new_archetype.channels.push(
                    component.0.new_archetype_channel()
                )
            }

            // 对新的 archetype 进行组件排序
            new_archetype.channels.sort_by_key(|channel|channel.component_id);

            archetypes.push(new_archetype);

            storage_lookup.new_archetype(new_archetype_index, key);

            new_archetype_index


        })
    };

    if *new_archetype_index != entity_location.archetype_index {
        let (old_archetype,new_archetype) = index_mut_twice(archetypes, entity_location.archetype_index, *new_archetype_index);

        World::migrate_entity(old_archetype, new_archetype, entities, entity, entity_location.index_within_archetype);

        // 添加新的组件到 [`Archetype`]
        let mut component_index = 0;
        for channel in new_archetype.channels.iter_mut() {
            let com = &mut components_and_component_ids[component_index];

            if channel.component_id == com.1 {
                channel.data.push(
                    &mut *com.0
                );
                component_index += 1;
                if component_index >= components_and_component_ids.len() {
                    break;
                }
            }

        }
    }else {
        let mut component_index = 0;
        let archetype = &mut world.archetypes[entity_location.archetype_index];

        for channel in archetype.channels.iter_mut() {
            let com = &mut components_and_component_ids[component_index];

            if channel.component_id == com.1 {
                channel.data.assign(entity_location.index_within_archetype, &mut *com.0);

                component_index += 1;
                if component_index >= components_and_component_ids.len() {
                    break;
                }
            }
        }
    }

    Ok(())

}


pub(crate) fn index_mut_twice<T>(slice:&mut [T], first:usize,second:usize) -> (&mut T,&mut T) {
    if first < second {
        let (a,b) = slice.split_at_mut(second);
        (&mut a[first],&mut b[0])
    }else {
        let (a,b) = slice.split_at_mut(first);
        (&mut b[0],&mut a[second])
    }
}


macro_rules! component_bundle_tuple_impls {
    ($count:tt,$(($index:tt,$tuple:ident)),*) => {
        impl<$($tuple:ComponentTrait,)*> ComponentBundleTrait for ($($tuple,)*) {
            #[allow(nor_snake_case)]
            fn add_to_entity(self,world:&mut World,entity:Entity) -> Result<(),MangoEcsError> {
                // (self,).add_to_entity(world,entity)
                // todo!()
                $(let mut $tuple = Some(self.$index);)*
                let mut component_and_component_ids = [$((&mut $tuple as &mut dyn AnyComponentTrait,get_component_id::<$tuple>()),)*];

                add_components_to_entity_inner(world,entity,&mut component_and_component_ids)

            }
        }
    };
}



